import CommonUtils from './CommonUtils';

// カテゴリ別アドバイス文
export const CATEGORY_ADVICES = {
  'A': 'A群は胃がんのリスクが低い群ですが、まったく胃がんが発生しないというわけではありません。油断せずに胃の調子に気を配り、症状があれば医師を受診して必要に応じた検査を受ける姿勢は必要です。',
  'B': 'B群は慢性胃炎はまだみられませんが、ピロリ菌には感染していて、胃がんのリスクがやや高い群です。生活習慣の見直しや必要な検診を受けるなどの心がけが必要です。',
  'C': 'C群は胃がんのリスクが高い群です。生活習慣の見直しや必要な検診を受けるなどの心がけが必要です。',
  'D': 'D群は胃がんのリスクが高い群です。生活習慣の見直しや必要な検診を受けるなどの心がけが必要です。',
};

// 喫煙アドバイス
export const SMOKING_ADVICES = ['これからも、たばこを吸わないようにしましょう。', '禁煙を心がけましょう。'];

// 塩蔵品アドバイス
export const SALINE_FOOD_ADVICES = ['これからも、なるべく控えめにしましょう。', 'たらこや塩辛など特に塩分濃度の高い食品は週１回未満など、なるべく控えめにしましょう。'];

// 胃がんの家族歴
export const FAMILY_ANAMNESIS_ADVICES = ['', '胃がんの家族歴がある場合、胃がんのリスクは高くなります。生活習慣など、改善できるものは積極的に取り組みましょう。'];

class GastricCancerLogic {

  /**
   * リスク計算
   * @param {Object.<number>} inputData 入力値(性別、年齢、ピロリ菌陰性陽性、慢性胃炎、喫煙習慣、塩蔵品の摂取、胃がん家族歴)
   */
  static calcRisk({ gender, age, helicobacterPyloriFlg, chronicGastritisFlg, smokingHabit, salineFood, familyAnamnesisFlg }) {

    age = CommonUtils.convertAge(age);// 69歳を超えた場合、69歳とみなす

    // 中間値生成(性別、喫煙、塩蔵品の摂取、カテゴリ)
    let { genderValue, smokingValue, salineFoodValue, category, categoryB, categoryC, categoryD } = this._calcMiddleParameter(gender, helicobacterPyloriFlg, chronicGastritisFlg, smokingHabit, salineFood);

    // diagnosis:カテゴリ群別のリスク、probability:あなたのリスク、最小、最大
    const results = {
      probability: {
        you: this._getProbability(genderValue, age, categoryB, categoryC, categoryD, smokingValue, salineFoodValue, familyAnamnesisFlg),
        min: this._getProbability(genderValue, age, categoryB, categoryC, categoryD, 0, 0, 0),
        max: this._getProbability(genderValue, age, categoryB, categoryC, categoryD, 1, 1, 1),
      },
      diagnosis: {
        category: category,
        categorya: this._getProbabilityBasedABC(genderValue, age, 0, 0, 0),
        categoryb: this._getProbabilityBasedABC(genderValue, age, 1, 0, 0),
        categoryc: this._getProbabilityBasedABC(genderValue, age, 0, 1, 0),
        categoryd: this._getProbabilityBasedABC(genderValue, age, 0, 0, 1),
        smokingFactor: this._getSmokingFactor(smokingValue),
        salineFoodFactor: this._getSalineFoodFactor(salineFoodValue),
        familyAnamnesisFactor: this._getFamilyAnamnesisFactor(familyAnamnesisFlg),
      },
    };
    return results;
  }

  /**
   * アドバイス生成
   * @param {Object.<number>} inputData 入力値(性別、年齢、ピロリ菌陰性陽性、慢性胃炎、喫煙習慣、塩蔵品の摂取、胃がん家族歴)
   */
  static takeAdvices({ gender, helicobacterPyloriFlg, chronicGastritisFlg, smokingHabit, salineFood, familyAnamnesisFlg }) {

    // 中間値生成(性別、喫煙、塩蔵品の摂取、カテゴリ)
    let { smokingValue, salineFoodValue, category } = this._calcMiddleParameter(gender, helicobacterPyloriFlg, chronicGastritisFlg, smokingHabit, salineFood);

    const results = {
      categoryRisk: category,
      categoryAdvices: CATEGORY_ADVICES[category],
      smokingAdvices: SMOKING_ADVICES[smokingValue],
      salineFoodAdvices: SALINE_FOOD_ADVICES[salineFoodValue],
      familyAnamnesisAdvices: FAMILY_ANAMNESIS_ADVICES[familyAnamnesisFlg],
    };

    return results;
  }

  /**
   * ABC群に基づく胃がんリスク算出
   * @param {string|number} genderValue 性別
   * @param {string|number} age 年齢
   * @param {string|number} categoryB B群(true:1,false:0)
   * @param {string|number} categoryC C群(true:1,false:0)
   * @param {string|number} categoryD D群(true:1,false:0)
   */
  static _getProbabilityBasedABC(genderValue, age, categoryB, categoryC, categoryD) {
    // PredLin(X)
    let f = this._predLinBasedABC(genderValue, age, categoryB, categoryC, categoryD);
    // S(t,Age)
    let S = this._stAgeBasedABC(10, age);
    // CumPr(10,X)
    return ((1 - Math.pow(S, Math.exp(f))) * 100);
  }

  /**
   * ABC群に基づく式1
   * @param {string|number} genderValue 性別
   * @param {string|number} age 年齢
   * @param {string|number} categoryB B群(true:1,false:0)
   * @param {string|number} categoryC C群(true:1,false:0)
   * @param {string|number} categoryD D群(true:1,false:0)
   */
  static _predLinBasedABC(genderValue, age, categoryB, categoryC, categoryD) {
    return (0.0655191 * (age - 58)) + (0.9278828 * genderValue) + (0.0318257 * (age - 58) * genderValue) + (2.0367911 * categoryB) + (2.6602014 * categoryC) + (2.6687267 * categoryD);
  }

  /**
   * ABC群に基づく式2
   * @param {string|number} t リスク算出対象期間(年)
   * @param {string|number} age 年齢
   */
  static _stAgeBasedABC(t, age) {
    return Math.exp(-1 * (((16.88 * Math.exp(-9.321119)) / (0.2273646 - 0.059972 * (age - 58)))) * (Math.exp(((0.2273646 - 0.059972 * (age - 58)) / 16.88) * t) - 1))
  }

  // 
  /**
   * リスク因子（喫煙、塩蔵品の摂取、胃がんの家族歴の状況）を加えた胃がんリスク算出
   * @param {string|number} genderValue 性別
   * @param {string|number} age 年齢
   * @param {string|number} categoryB B群(true:1,false:0)
   * @param {string|number} categoryC C群(true:1,false:0)
   * @param {string|number} categoryD D群(true:1,false:0)
   * @param {string|number} smokingValue 喫煙習慣
   * @param {string|number} salineFoodValue 塩蔵品の摂取
   * @param {string|number} familyAnamnesisFlg 胃がんの家族歴
   */
  static _getProbability(genderValue, age, categoryB, categoryC, categoryD, smokingValue, salineFoodValue, familyAnamnesisFlg) {
    let f = this._predLin(genderValue, age, categoryB, categoryC, categoryD, smokingValue, salineFoodValue, familyAnamnesisFlg);
    let S = this._stAge(10, age);
    return ((1 - Math.pow(S, Math.exp(f))) * 100);
  }

  /**
   * リスク因子（喫煙、塩蔵品の摂取、胃がんの家族歴の状況）を加えた式1
   * @param {string|number} genderValue 性別
   * @param {string|number} age 年齢
   * @param {string|number} categoryB B群(true:1,false:0)
   * @param {string|number} categoryC C群(true:1,false:0)
   * @param {string|number} categoryD D群(true:1,false:0)
   * @param {string|number} smokingValue 喫煙習慣
   * @param {string|number} salineFoodValue 塩蔵品の摂取
   * @param {string|number} familyAnamnesisFlg 胃がんの家族歴
   */
  static _predLin(genderValue, age, categoryB, categoryC, categoryD, smokingValue, salineFoodValue, familyAnamnesisFlg) {
    return (0.0675376 * (age - 58)) +
      (0.7772737 * genderValue) +
      (0.0321313 * (age - 58) * genderValue) +
      (0.3101926 * smokingValue) +
      (0.2478445 * salineFoodValue) +
      (0.3129599 * familyAnamnesisFlg) +
      (2.0251122 * categoryB) +
      (2.6288531 * categoryC) +
      (2.6455843 * categoryD);
  }

  /**
   * リスク因子（喫煙、塩蔵品の摂取、胃がんの家族歴の状況）を加えた式2
   * @param {string|number} t リスク算出対象期間(年)
   * @param {string|number} age 年齢
   */
  static _stAge(t, age) {
    return Math.exp(-1 * (((16.88 * Math.exp(-9.483213)) / (0.241709 - 0.0593 * (age - 58)))) * (Math.exp(((0.241709 - 0.0593 * (age - 58)) / 16.88) * t) - 1))
  }

  /**
   * 計算用の中間値生成(性別、喫煙、塩蔵品の摂取、カテゴリ)
   * @param {string|number} gender 性別
   * @param {string|number} pylori ピロリ菌陰性陽性
   * @param {string|number} atrophicGastritis 慢性胃炎
   * @param {string|number} smokingHabit 喫煙習慣
   * @param {string|number} salineFood 塩蔵品の摂取
   */
  static _calcMiddleParameter(gender, pylori, atrophicGastritis, smokingHabit, salineFood) {

    // 性別
    let genderValue = this._getGenderValue(gender);
    // 喫煙の有無
    let smokingValue = this._getSmokingValue(smokingHabit);
    // 塩蔵品の摂取
    let salineFoodValue = this._getSalineFoodValue(salineFood);
    // カテゴリ(A～D群)
    let { category, categoryB, categoryC, categoryD } = this._getCategory(pylori, atrophicGastritis);

    return { genderValue, smokingValue, salineFoodValue, category, categoryB, categoryC, categoryD };
  }

  /**
   * 画面入力値 男性：１、女性：２
   * 計算式 男性：１、女性：０
   * @param {string|number} gender 
   */
  static _getGenderValue(gender) {
    return gender === 1 ? 1 : 0;
  }

  /**
   * 塩蔵品の摂取
   * 0:ない 1：ある
   * @param {string|number} salineFood 
   */
  static _getSalineFoodValue(salineFood) {
    return salineFood > 1 ? 1 : 0;
  }

  /**
   * 喫煙の有無
   * ０:ない 1:ある
   * @param {string|number} smokingHabit 
   */
  static _getSmokingValue(smokingHabit) {
    return smokingHabit > 1 ? 0 : 1;
  }

  /**
   * 塩蔵品の摂取（リスク因子）
   * －:ない ＋：ある
   * @param {string|number} salineFoodFactor
   */
  static _getSalineFoodFactor(salineFoodFactor) {
    return salineFoodFactor === 1 ? '＋' : '－';
  }
  
  /**
   * 喫煙の有無（リスク因子）
   * －:ない ＋：ある
   * @param {string|number} smokingFactor
   */
  static _getSmokingFactor(smokingFactor) {
    return smokingFactor === 1 ? '＋' : '－';
  }

  /**
   * 家族歴の状況（リスク因子）
   * －:ない ＋：ある
   * @param {string|number} familyAnamnesisFactor
   */
  static _getFamilyAnamnesisFactor(familyAnamnesisFactor) {
    return familyAnamnesisFactor === 1 ? '＋' : '－';
  }
  
  /**
   * カテゴリ取得
   * @param {string|number} pylori ピロリ菌陰性陽性
   * @param {string|number} atrophicGastritis 慢性胃炎
   */
  static _getCategory(pylori, atrophicGastritis) {

    let category = '';
    let categoryA = 0;
    let categoryB = 0;
    let categoryC = 0;
    let categoryD = 0;

    // ピロリ陽性 胃炎なし
    if (pylori === 1 && atrophicGastritis === 0) {
      categoryB = 1;
      category = 'B';
      // ピロリ陽性 胃炎あり
    } else if (pylori === 1 && atrophicGastritis === 1) {
      categoryC = 1;
      category = 'C';
      // ピロリ陰性 胃炎あり
    } else if (pylori === 0 && atrophicGastritis === 1) {
      categoryD = 1;
      category = 'D';
    } else {
      categoryA = 1;
      category = 'A';
    }

    return { category, categoryA, categoryB, categoryC, categoryD };
  }

}

export default GastricCancerLogic
